#include "tcp.h"

typedef struct
{
	int type;
	int opt;
}MSG;

int Auto_led(void)
{
	int fd;
	int on=0;
	fd=open("/dev/led0",O_RDWR);
	if(fd<0)
	{
		perror("open");
		exit(1);
	}

	on=0;
	write(fd,&on,4);
	sleep(1);
	on=1;
	write(fd,&on,4);
	sleep(1);

	return 0;
}

int Manual_led(MSG *msg)
{
	int fd;
	int on=0;
	fd=open("/dev/led0",O_RDWR);
	if(fd<0)
	{
		perror("open");
		exit(1);
	}
	if(msg->opt==0)
	{
		on=0;
		write(fd,&on,4);
	}
	if(msg->opt==1)
	{
		on=1;
		write(fd,&on,4);
	}
	close(fd);
	return 0;
}

int main(int argc, const char *argv[])
{
	int sockfd,acceptfd;
	char ipv4_addr[16];
	socklen_t pstrlen;
	char buff[16];
	struct sockaddr_in serveraddr,cliaddr;
	pid_t pid;

	if(argc<2)
	{
		printf("Usage : %s <port>\n",argv[0]);
		return -1;
	}

	if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
	{
		perror("socket");
		exit(-1);
	}
	bzero(&serveraddr,sizeof(serveraddr));
	serveraddr.sin_family=AF_INET;
	serveraddr.sin_port=htons(atoi(argv[1]));
	serveraddr.sin_addr.s_addr=htons(INADDR_ANY);

	if(bind(sockfd,(struct sockaddr *)&serveraddr,sizeof(serveraddr))<0)
	{
		perror("bind");
		exit(-1);
	}

	if(listen(sockfd,5)<0)
	{
		perror("lieten");
		exit(-1);
	}
	signal(SIGCHLD,SIG_IGN);
	
	pstrlen=sizeof(cliaddr);
	while(1)
	{
		Auto_led();
		if((acceptfd=accept(sockfd,(struct sockaddr *)&cliaddr,&pstrlen))<0)
		{
			perror("accept");
			exit(-1);
		}
		if(!inet_ntop(AF_INET,(void *)&cliaddr.sin_addr,ipv4_addr,sizeof(buff)))
		{
			perror("inet_ntop");
			exit(-1);
		}
		printf("client (%s:%d)connected\n",ipv4_addr,ntohs(serveraddr.sin_port));
		if((pid=fork())<0)
		{
			perror("fork");
			exit(-1);
		}
		else if(pid==0)
		{
			do_client(acceptfd);
		}
		else
		{
			close(acceptfd);
		}
	}
	return 0;
}


int do_client(int acceptfd)
{
	MSG msg;
	while(recv(acceptfd,&msg,sizeof(msg),0)>0)
	{
		switch(msg.type)
		{
		case 'A':
			Auto_led();
			break;
		case 'M':
			Manual_led(&msg);
			break;
		default:
			printf("Invalid message!\n");
		}
	}
	printf("client exit\n");
	close(acceptfd);
	exit(0);

	return 0;
}
